<?php


/**
 * Camada de Abstração para a utilização do banco de dados MySQL
 * @author heekinho (a partir de análise do script AuroraGPT)
 */
class Mysql {
	var $dbhost = 'localhost';	// Hostname, geralmente localhost.
	var $dbname = 'mydb';		// Nome do banco de dados no servidor.
	var $dbuser = 'root';		// Usuário para acessar o banco de dados
	var $dbpass = 'root';		// Senha de acesso do usuário

	var $link_id  = 0;  		// Resultado da conexão mysql_connect().
	var $query_id = 0; 			// Resultado da mais recente query mysql_query().	
	var $mtrecord = array();	// Atual resultado de mysql_fetch_array().
	var $resultset = array();	// Resultset Completo!!! Possui todos os resultados da query.
	var $row;           		// Numero da linha atual.
	var $map_fields = array();  // Faz o mapeamento dos titulos para uso posterior.
	
	var $num_queries = 0;		// Número de queries executadas na conexão.
	var $errno    = 0;  		// Numero do erro na query
	var $error    = ""; 		// Descrição textual do erro na query



	/**
	 * Constrói a Camada de Abstração com o MySQL.
	 * @author heekinho
	 * @param string $dbhost Hostname do DB.
	 * @param string $dbname Nome do DB.
	 * @param string $dbuser Usuário do DB.
	 * @param string $dbpass Senha do DB.
	 * @return Mysql
	 */
	public function Mysql($dbhost, $dbname, $dbuser, $dbpass){
		$this->dbhost = $dbhost;
		$this->dbname = $dbname;
		$this->dbuser = $dbuser;
		$this->dbpass = $dbpass;

		$this->connect();
	}

	
	/**
	 * Estabelece a conexão com o banco de dados.
	 * @author heekinho
	 */
	private function connect(){
		// Verifica a conectividade e executa a ação correspondente.
		if($this->link_id == 0){
			$this->link_id = mysql_connect($this->dbhost, $this->dbuser, $this->dbpass);
				
			// Verifica a conexão recém estabelecida.
			if(!$this->link_id) $this->halt("Falha na conexão com o banco de dados (LinkID == false)");
				
			// Verifica a possibilidade de uso do banco de dados especificado.
			if(!mysql_query("use $this->dbname", $this->link_id)) $this->halt("Não foi possível conectar-se a: $this->dbname");
		}
	}


	/**
	 * Executa uma consulta ao banco de dados
	 * @author heekinho
	 * @param string $query_string
	 * @return query_id Identificador da consulta.
	 */
	public function query($sql){
		$this->num_queries++;
		$this->query_id = mysql_query($sql, $this->link_id);
		$this->row = 0;
		$this->errno = mysql_errno();
		$this->error = mysql_error();
		if(!$this->query_id) $this->halt("SQL inválido: $sql");

		// Se for uma consulta (SELECT), atualiza os dados.
		$tofetch = strpos($sql, "SELECT");
		if($tofetch !== false){
            $this->fetch_fields();
			$this->fetch_resultset();
		}

		return $this->query_id;
	}


	/**
	 * Obtém um dado a partir da tabela e da coluna
	 * @author heekinho
	 * @param string $table
	 * @param string $name
	 * @return value
	 */
	public function get($table, $name){
		return $this->mtrecord[$table][$name];
	}
	

	/**
	 * Obtém o registro corrente em formato matriz[tabela][campo]
	 * @author heekinho
	 * @return array
	 */
	public function get_record(){
		return $this->mtrecord;
	}
  

	/**
	 * Passa para o próximo registro da consulta.
	 * @author heekinho
	 * @return flag: próximo registro válido?
	 */
	public function next_record() {
		$this->fetch_resultset();
		$this->row++;
		$this->errno = mysql_errno();
		$this->error = mysql_error();

		// Verifica se há um próximo registro
		$stat = is_array($this->mtrecord);
		if(!$stat) {
			mysql_free_result($this->query_id);
			$this->query_id = 0;
		}

		// Retorna a flag que diz se há próximo registro
		return $stat;
	}

	
	/**
	 * Obtém o número de registro da consulta.
	 * @author heekinho
	 * @return int qtd_rows
	 */
	public function num_rows() {
		return mysql_num_rows($this->query_id);
	}

	
	/**
	 * Obtém quantidade de campos.
	 * @author heekinho
	 * @return int qtd_campos
	 */
	public function num_fields() {
		return mysql_num_fields($this->query_id);
	}

	
	/**
	 * Captura a matriz de consulta, com tabelas, colunas e valores.
	 * @author heekinho
	 * @return bool
	 */
	private function fetch_resultset(){
		$results = $this->query_id;
		if(isset($results)) {
			
			// Atribui cada quem a cada quem...
			if ($row = mysql_fetch_row($results)) {
				$drow = array();

				foreach ($row as $index => $field) {
					list($table, $column) = $this->map_fields[$index];
					$drow[$table][$column] = $row[$index];
				}

				$this->mtrecord = $drow;
				return $this->mtrecord;
			}
			return false;
		}
		return false;
	}
	
	
	/**
	 * Obtém a matriz de resultados completa.
	 * Faz semelhante ao mysql_fetch_assoc, mas já retorna a matriz completa, com todos os resultados.
	 * Para evitar o mapeamento por alias, foi implementado com especificação de tabelas.
	 * @author heekinho
	 * @see mysql_fetch_assoc
	 * @return array
	 */
	public function get_complete_resultset(){
		$complete_resultset = array();
		
		if(isset($this->query_id)) {
			// Posiciona o ponteiro no início.
			mysql_data_seek($this->query_id, 0);
			while ($row = mysql_fetch_row($this->query_id)) {
				// Itera e armazena todos os resultados, obtendo-se a matriz completa.
				$drow = array();
				foreach ($row as $index => $field) {
					list($table, $column) = $this->map_fields[$index];
					$drow[$table][$column] = $row[$index];
				}
				
				array_push($complete_resultset, $drow);
			}
		}
		mysql_data_seek($this->query_id, $this->row);
		return $complete_resultset;
	}
	
	/**
	 * Faz o mapeamento dos fields presentes na consulta.
	 * @author heekinho
	 */
	private function fetch_fields(){
		mysql_field_seek($this->query_id, 0);
		while ($column = mysql_fetch_field($this->query_id)) array_push($this->map_fields, array($column->table, $column->name));
	}


	/**
	 * Informa erro ocorrido no banco de dados.
	 * @author heekinho
	 * @param string $msg Mensagem de erro a ser impressa.
	 */
	private function halt($msg) {
		echo "<div><strong>Database Error:</strong> $msg</div>";
		echo "<div><strong>MySQL Error:</strong> $this->errno ($this->error)</div>";
		die("<div>Session halted.</div>");
	}


	/**
	 * Fecha a conexão com o banco de dados
	 * @author heekinho
	 * @return bool
	 */
	public function sql_close() {
		if($this->link_id){
			if($this->query_id) @mysql_free_result($this->query_id);
			return @mysql_close($this->link_id);
		}
		else return false;
	}
}

?>